package com.car.rental.order.service.impl;

import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.internal.util.AlipaySignature;
import com.car.rental.common.core.exception.BusinessException;
import com.car.rental.common.core.response.ResponseResult;
import com.car.rental.common.utils.JsonUtils;
import com.car.rental.order.entity.PaymentRecord;
import com.car.rental.order.entity.RentalOrder;
import com.car.rental.order.enums.PaymentStatus;
import com.car.rental.order.service.AlipayService;
import com.car.rental.order.service.MessageService;
import com.car.rental.order.service.PaymentService;
import com.car.rental.order.service.OrderService;
import com.car.rental.order.util.AlipaySignUtils;
import com.car.rental.order.config.AlipayConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class AlipayServiceImpl implements AlipayService {
    
    private final AlipayClient alipayClient;
    private final AlipayConfig alipayConfig;
    private final MessageService messageService;
    private final PaymentService paymentService;
    private final OrderService orderService;
    
    @Override
    public ResponseResult<String> createPayment(PaymentRecord payment) {
        try {
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            request.setNotifyUrl(alipayConfig.getNotifyUrl());
            request.setReturnUrl(alipayConfig.getReturnUrl().replace("${orderNo}", payment.getOrderNo()));
            
            // 构建请求参数
            Map<String, Object> bizContent = new HashMap<>();
            bizContent.put("out_trade_no", payment.getPaymentNo());
            bizContent.put("total_amount", payment.getAmount().toString());
            bizContent.put("subject", "车辆租赁订单支付");
            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
            
            request.setBizContent(JsonUtils.toJsonString(bizContent));
            
            log.info("调用支付宝接口，参数：{}", request.getBizContent());
            String form = alipayClient.pageExecute(request).getBody();
            log.info("支付宝返回表单：{}", form);
            
            return ResponseResult.success(form);
        } catch (Exception e) {
            log.error("创建支付宝支付订单失败", e);
            throw new BusinessException("创建支付订单失败");
        }
    }

    @Override
    public void handleCallback(Map<String, String> params) {
        try {
            log.info("处理支付宝回调开始，参数：{}", params);
            
            // 1. 验证签名
            if (!verifySign(params)) {
                throw new BusinessException("支付宝回调签名验证失败");
            }

            // 2. 获取交易状态和订单号
            String tradeStatus = params.get("trade_status");
            String outTradeNo = params.get("out_trade_no");
            String tradeNo = params.get("trade_no");
            
            log.info("支付宝回调 - 交易状态：{}，商户订单号：{}，支付宝交易号：{}", tradeStatus, outTradeNo, tradeNo);
            
            // 3. 获取支付记录并更新支付宝返回信息
            PaymentRecord payment = paymentService.getByPaymentNo(outTradeNo);
            if (payment == null) {
                throw new BusinessException("支付记录不存在：" + outTradeNo);
            }
            
            // 4. 更新支付记录信息
            payment.setTradeNo(tradeNo);
            payment.setNotifyTime(LocalDateTime.now());
            payment.setNotifyData(JsonUtils.toJsonString(params));
            
            // 添加日志验证字段填充
            log.info("支付记录更新 - 支付宝交易号：{}，通知时间：{}，回调数据：{}", 
                payment.getTradeNo(), 
                payment.getNotifyTime(), 
                payment.getNotifyData());

            // 5. 处理支付状态
            if ("TRADE_SUCCESS".equals(tradeStatus)) {
                payment.setStatus(PaymentStatus.SUCCESS.getCode());
                paymentService.updateById(payment);
                paymentService.paymentSuccess(outTradeNo);
                log.info("支付宝回调处理成功 - 订单支付成功：{}", outTradeNo);
            } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                payment.setStatus(PaymentStatus.FAILED.getCode());
                paymentService.updateById(payment);
                paymentService.paymentFailed(outTradeNo, "交易关闭");
                log.info("支付宝回调处理成功 - 订单支付失败：{}", outTradeNo);
            } else {
                log.warn("支付宝回调 - 未处理的交易状态：{}，订单号：{}", tradeStatus, outTradeNo);
            }
        } catch (Exception e) {
            log.error("处理支付宝回调失败", e);
            throw new BusinessException("处理支付宝回调失败：" + e.getMessage());
        }
    }

    @Override
    public boolean verifySign(Map<String, String> params) {
        try {
            return AlipaySignature.rsaCheckV1(
                params,
                alipayConfig.getAlipayPublicKey(),
                "UTF-8",
                "RSA2"
            );
        } catch (Exception e) {
            log.error("验证支付宝签名失败", e);
            return false;
        }
    }

    @Override
    public ResponseResult<Boolean> queryPaymentStatus(String paymentNo) {
        // 先检查本地支付记录
        PaymentRecord payment = paymentService.getByPaymentNo(paymentNo);
        if (payment == null) {
            log.warn("支付记录不存在：{}", paymentNo);
            return ResponseResult.success(false);
        }

        // 如果本地已经是成功状态，直接返回
        if (PaymentStatus.SUCCESS.getCode().equals(payment.getStatus())) {
            return ResponseResult.success(true);
        }

        // 最多重试3次
        int maxRetries = 3;
        int retryCount = 0;
        Exception lastException = null;

        while (retryCount < maxRetries) {
            try {
                // 查询支付宝交易状态
                AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
                Map<String, Object> bizContent = new HashMap<>();
                bizContent.put("out_trade_no", paymentNo);
                request.setBizContent(JsonUtils.toJsonString(bizContent));

                log.info("查询支付宝交易状态，第{}次尝试，参数：{}", retryCount + 1, request.getBizContent());
                AlipayTradeQueryResponse response = alipayClient.execute(request);
                
                if (response.isSuccess()) {
                    log.info("查询支付宝交易状态成功，订单号：{}，交易状态：{}", paymentNo, response.getTradeStatus());
                    return ResponseResult.success("TRADE_SUCCESS".equals(response.getTradeStatus()));
                }
                
                // 处理特定错误码
                if ("ACQ.TRADE_NOT_EXIST".equals(response.getSubCode())) {
                    log.info("交易未创建或已关闭：{}", paymentNo);
                    return ResponseResult.success(false);
                }
                
                log.warn("查询支付宝交易状态失败：code={}, msg={}, sub_code={}, sub_msg={}", 
                    response.getCode(), response.getMsg(), response.getSubCode(), response.getSubMsg());
                
                // 如果是系统错误，则重试
                if ("SYSTEM_ERROR".equals(response.getCode()) || 
                    "NETWORK_ERROR".equals(response.getCode()) ||
                    response.getCode() == null) {
                    retryCount++;
                    if (retryCount < maxRetries) {
                        Thread.sleep(1000); // 等待1秒后重试
                        continue;
                    }
                }
                
                return ResponseResult.success(false);
            } catch (Exception e) {
                lastException = e;
                log.error("查询支付宝交易状态异常，第{}次尝试", retryCount + 1, e);
                retryCount++;
                if (retryCount < maxRetries) {
                    try {
                        Thread.sleep(1000); // 等待1秒后重试
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                    continue;
                }
            }
        }

        if (lastException != null) {
            log.error("查询支付宝支付状态失败，已重试{}次", maxRetries, lastException);
            throw new BusinessException("查询支付状态失败，请稍后重试");
        }

        return ResponseResult.success(false);
    }
} 